home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 136_01 / cmaze.c < prev    next >
Text File  |  1980-01-01  |  17KB  |  973 lines

  1. /*    HEADER:  CUG136.19;
  2.     TITLE:        CMAZE;
  3.     VERSION:    1.00;
  4.     DATE:        5/29/1984;
  5.     DESCRIPTION:    "3-D Maze Game";
  6.     KEYWORDS:    game,maze;
  7.     SYSTEM:        CP/M;
  8.     FILENAME:    CMAZE.C;
  9.     AUTHORS:    R. Rodman;
  10.     COMPILERS:    C/80;
  11. */
  12.  
  13. /*        >< CMAZE by R. Rodman ><
  14.  
  15.     5/6/81 v0.8
  16.     9/14/81 v0.9 (Basic-E)
  17.     1/15/82 back to MBASIC
  18.     840512 convert to c
  19.     840513, 840514, 840515, 840516, 840518 rr continue conversion
  20.     840529 fix boxes 1.00
  21.  
  22.     Robots move crudely.
  23.     Find objects in boxes:  Compass - Radio - etc.
  24.     Shoot algorithm could show an alternating / \ or something.
  25.     Solving maze is difficult and gets boring.  Tools would help. */
  26.  
  27. #define MX 15           /* define maximum X dimension of maze */
  28. #define MY 10        /* define maximum Y dimension of maze */
  29. #define MXMY 150    /* product of mx and my */
  30.  
  31. #define CLRSCN "\033+"
  32. #define REVVID "\033G4"
  33. #define NORVID "\033G0"
  34. #define CURBEG "\033="
  35. #define CLREOS "\033Y"
  36. #define CUROFF "\033.0"
  37. #define CURON "\033.2"
  38.  
  39.     int maze[ MX ][ MY ];
  40.  
  41.     int rx[ 4 ], ry[ 4 ];
  42.     char *robot[ 4 ][ 9 ] = {
  43.         "  _______",
  44.         " / o' `o \\",
  45.         " \\ ----- /",        /* close robot, height 9 */
  46.         "  [TTTTT]",
  47.         " /[=====]\\",
  48.         "/ [MMMMM] \\",
  49.         ") [=====] (",
  50.         " / \\   / \\",
  51.         "/   \\ /   \\",
  52.  
  53.         " _____",
  54.         "/ o o \\",
  55.         "\\ --- /",
  56.         "/[TTT]\\",        /* height 7 */
  57.         ")[===](",
  58.         " [===]",
  59.         "/ \\ / \\", "", "",
  60.  
  61.         " ____",
  62.         "< o_o>",
  63.         "/[TT]\\",
  64.         " [==]",        /* height 5 */
  65.         "/ \\/ \\", "", "", "", "",
  66.  
  67.         "<oo>",
  68.         "/[]\\",        /* dist 4, height 3 */
  69.         "/\\/\\", "", "", "", "", "", ""
  70.     };
  71.  
  72.     int boxx[ 4 ], boxy[ 4 ];
  73.     char *boxes[ 3 ][ 3 ] = {
  74.         " ____",
  75.         "|\\ ___\\",
  76.         " \\|____|",
  77.  
  78.         " __",
  79.         "<__>", "",
  80.  
  81.         "<>", "", "" 
  82.     };
  83.  
  84.     int seed;
  85.  
  86.     int plyr_x, plyr_y, plyr_face;        /* player x, y, direction */
  87.  
  88.     int alive;        /* nonzero while alive */
  89.     int won;        /* won game */
  90.  
  91.     int comp, radi, shots;
  92.  
  93.     int repaint;        /* nonzero to cause repaint */
  94.  
  95. /* main program */
  96.  
  97. main()
  98. {
  99.     instructions();        /* print instructions */
  100.  
  101.     randomize();            /* randomize seed */
  102.     generate();        /* generate maze */
  103.  
  104.     init_robots();
  105.     init_boxes();
  106.  
  107.     plyr_face = 2;            /* face to "east" */
  108.  
  109.     alive = 1;
  110.     repaint = 1;
  111.     won = 0;
  112.     
  113.     while( alive && ! won ) {
  114.         if( repaint ) {
  115.             depict();
  116.             ck_boxes();
  117.             repaint = 0;
  118.         }
  119.         ck_instruments();
  120.         if( ck_robots()) alive = 0;
  121.             else {
  122.             get_command();
  123.             update_robots();
  124.         }
  125.     }
  126.     sound( ",,,,,,,,,,,,,,,," );    /* shut up */
  127.     puts( CURON );
  128. }
  129.  
  130. /* return random number between 0 and n-1 */
  131.  
  132. fnr( n )
  133. int n;
  134. {
  135.     return ( rnd() % n );
  136. }
  137.  
  138. int rnd()
  139. {
  140.     seed = seed * 3;
  141.     if( seed > 10000 ) seed = seed / 4;
  142.     return seed;
  143. }
  144.  
  145. randomize()
  146. {
  147.     int i;
  148.     seed = 1;
  149.     puts( "<Press a key>" );
  150.     while( bdos( 6, 0xFF ) == 0 ) i = rnd();
  151. }
  152.  
  153. goxy( x, y )
  154. int x, y;
  155. {
  156.     puts( CURBEG );
  157.     putchar( y + 32 );
  158.     putchar( x + 32 );
  159. }
  160.  
  161. /* print instructions */
  162.  
  163. instructions()
  164. {
  165.     puts( CLRSCN );
  166.     puts( "\t\t\t> > > A M A Z E ! < < <\n\n" );
  167.     puts( "\nVersion 1.00\n\n" );
  168.     puts( "This program presents a Perspective Maze Display on your\n" );
  169.     puts( "terminal.  Your object is to get through this maze.\n" );
  170.     puts( "four robots in the maze which will attempt to\n" );
  171.     puts( "capture you.  You have a laser pistol to protect yourself;\n" );
  172.     puts( "the pistol can fire only 5 shots.\n\n" );
  173.     puts( "On each turn, you will be asked for a command, which must\n" );
  174.     puts( "be made up of any combination of:\n\n" );
  175.     puts( "S to step forward one square\n" );
  176.     puts( "L to turn to your left, R to turn to your right\n" );
  177.     puts( "F to fire the laser pistol\n" );
  178.     puts( "O to open a box\n\n" );
  179.     puts( "I am generating the maze now.\n" );
  180.  
  181.     sound( ",,,,,,,,,,,,,,,," );    /* turn sound off */
  182. }
  183.  
  184. /*    >< Generate Maze ><
  185.  
  186. This program uses the algorithm described by R J Bishop
  187. in his article in Byte Oct 78 P 136 */
  188.  
  189. generate()
  190. {
  191.     int x, y;
  192.     int lc, oc, wf, bx, by;
  193.     int to_bit, from_bit, tp, path;
  194.     int qu[ MXMY ][ 2 ];
  195.  
  196.     for( x = 0; x < MX; ++x )
  197.         for( y = 0; y < MY; ++y )
  198.             maze[ x ][ y ] = 0;
  199.  
  200.     lc = 0;        /* last cell in queue */
  201.     oc = 0;        /* last cell taken out of queue */
  202.     wf = 0;        /* found win path yet? */
  203.  
  204.     plyr_x = 0;
  205.     plyr_y = fnr( MY );    /* player start position */
  206.  
  207.     bx = plyr_x;
  208.     by = plyr_y;        /* random walk start position */
  209.     
  210.     x = 1; y = 1;        /* junk values to cause loop to execute */
  211.  
  212. /* loop while any valid starting points for walks are in the queue */
  213.  
  214.     while( oc <= lc ) {
  215.  
  216. /* random walk from bx, by until we come to a dead end or generate a goal. */
  217.  
  218.         x = bx;
  219.         y = by;
  220.  
  221.         while( x + y ) {
  222.  
  223. /* inner loop, try to move to another square from bx, by */
  224.  
  225.             tp = 0;        /* tried path */
  226.             while( tp < 15 ) {
  227.                 x = bx;
  228.                 y = by;
  229.                 path = fnr( 4 );    /* get random path */
  230.  
  231.                 switch( path ) {
  232.  
  233.                 case 0 :     to_bit = 1;
  234.                         from_bit = 2;
  235.                         --x;
  236.                         break;
  237.  
  238.                 case 1 :     to_bit = 2;
  239.                         from_bit = 1;
  240.                         ++x;
  241.                         break;
  242.  
  243.                 case 2 :     to_bit = 4;
  244.                         from_bit = 8;
  245.                         --y;
  246.                         break;
  247.  
  248.                 case 3 :     to_bit = 8;
  249.                         from_bit = 4;
  250.                         ++y;
  251.                         break;
  252.                 }
  253.  
  254.                 tp = tp | to_bit;
  255.  
  256. /* break out of loop if we hit an empty square */
  257.  
  258.                 if( x >= 0 && x <= ( MX - 2 )
  259.                     && y >= 0 && y < MY )
  260.                     if( maze[ x ][ y ] == 0 ) break;
  261.  
  262. /* otherwise try again */
  263.  
  264.             }
  265.  
  266. /* see if we got out, or just fell out */
  267.  
  268.             if( tp >= 15 ) {
  269.                 x = 0;        /* no path left */
  270.                 y = 0;
  271.             }
  272.  
  273. /* if not, we must have a good path here */
  274.  
  275.             if( x + y ) {
  276.  
  277. /* flag where we opened path to */
  278.  
  279.                 maze[ bx ][ by ] = maze[ bx ][ by ] | to_bit;
  280.  
  281.                 bx = x;        /* new origin */
  282.                 by = y;
  283.  
  284. /* flag where we opened path from */
  285.  
  286.                 maze[ bx ][ by ] = maze[ bx ][ by ] | from_bit;
  287.  
  288.                 qu[ lc ][ 0 ] = bx;
  289.                 qu[ lc ][ 1 ] = by;    /* save in queue */
  290.                 ++lc;
  291.  
  292. /* have we no solution yet, and are we on next to last column of maze? */
  293.  
  294.                 if( wf == 0 && bx == ( MX - 2 )) {
  295.  
  296. /* if so, generate a goal */
  297.  
  298.                     ++wf;        /* mark goal found */
  299.  
  300.                     maze[ bx ][ by ] =
  301.                         maze[ bx ][ by ] | 2;
  302.                     maze[ MX - 1 ][ by ] = 1;
  303.  
  304.                     x = 0;        /* cause no path */
  305.                     y = 0;
  306.                 }
  307.             }
  308.         }
  309.  
  310. /* no path. what do you do now? */
  311.  
  312.         if( lc == MXMY ) break;    /* give up if we've used all */
  313.  
  314.         bx = qu[ oc ][ 0 ];    /* pull next starting point */
  315.         by = qu[ oc ][ 1 ];    /* from the queue */
  316.         ++oc;
  317.     }
  318. }
  319.  
  320. init_robots()
  321. {
  322.     int i;
  323.     for( i = 0; i < 4; ++i ) {
  324.         rx[ i ] = fnr( MX - 3 ) + 1;
  325.         ry[ i ] = fnr( MY );
  326.     }
  327.  
  328.     shots = 5;
  329. }
  330.  
  331. init_boxes()
  332. {
  333.     int i;
  334.     for( i = 0; i < 4; ++i ) {
  335.         boxx[ i ] = fnr( MX - 3 ) + 1;
  336.         boxy[ i ] = fnr( MY );
  337.     }
  338.  
  339.     comp = 0;    /* you have no compass */
  340.     radi = 0;    /* you have no radio */
  341.     shots = 5;
  342. }
  343.  
  344. /* depict view from current position and location */
  345.  
  346. depict()
  347. {
  348.     int lsm, rsm;    /* left side, right side masks */
  349.     int wx, wy;    /* wall x, y */
  350.     int mw, wf, w;
  351.     int lw[ 6 ], rw[ 6 ];
  352.     char ldol, rdol, wdol[ 3 ];
  353.     int js, l1, l2, j1, j2, l, j, mi; 
  354.  
  355. /* define side masks */
  356.     
  357.     switch( plyr_face ) {
  358.  
  359.     case 1 :    lsm = 8;
  360.             rsm = 4;
  361.             break;
  362.  
  363.     case 2 :    lsm = 4;
  364.             rsm = 8;
  365.             break;
  366.  
  367.     case 4 :    lsm = 1;
  368.             rsm = 2;
  369.             break;
  370.  
  371.     case 8 :    lsm = 2;
  372.             rsm = 1;
  373.             break;
  374.     }
  375.  
  376. /* now we know which way to look */
  377.  
  378.     wx = plyr_x;
  379.     wy = plyr_y;
  380.     mw = 4;        /* max wall even if we don't run into one */
  381.     wf = 0;
  382.  
  383.     w = 0;
  384.  
  385.     while( w < mw ) {
  386.  
  387.         lw[ w ] = maze[ wx ][ wy ] & lsm;
  388.         rw[ w ] = maze[ wx ][ wy ] & rsm;
  389.  
  390. /* mw is the wall beyond which we cannot see */
  391.  
  392.         if( ! ( maze[ wx ][ wy ] & plyr_face )) {
  393.             mw = w;
  394.             lw[ w + 1 ] = 1;
  395.             rw[ w + 1 ] = 1;
  396.         }
  397.  
  398.         if( wx == MX - 1 ) wf = 1;
  399.  
  400.         switch( plyr_face ) {
  401.         case 1 :    --wx;    break;
  402.         case 2 :    ++wx;    break;
  403.         case 4 :    --wy;    break;
  404.         case 8 :    ++wy;    break;
  405.         }
  406.  
  407.         ++w;
  408.     }
  409.  
  410. /* got wall arrays, now draw them */
  411.  
  412.     puts( CLRSCN );        /* clear the screen */
  413.     puts( CUROFF );
  414.  
  415.     ldol = '\\';
  416.     rdol = '/';
  417.  
  418. /* js is 1 for top half of screen, -1 for bottom */
  419.  
  420.     for( js = 1; js >= -1; js -= 2 ) {
  421.  
  422.         if( js == 1 ) {
  423.             l1 = 0;
  424.             l2 = 4;
  425.             j1 = 0;
  426.             j2 = 1;
  427.         } else {
  428.             l1 = 4;
  429.             l2 = 0;
  430.